package cs423.loadBalancer.core;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import android.content.Context;
import android.os.Environment;
import android.widget.Toast;

//Aggregation phase
public class Aggregation implements Runnable{

	String type;
	
	public Aggregation(String type)
	{
		this.type = type;
	}
	
	
	
	
	public void updateResult(Socket ClientS) throws IOException {
		// Again, probably better to store these objects references in the
		// support class
		System.out.println("inside AGGREGATION ACTIVE, but nothing read now");

		InputStream in = null;
		try {
			in = ClientS.getInputStream();
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("open input stream exception");
			throw new IOException();
		}
		DataInputStream dis = new DataInputStream(in);

		while(true){
			int pos = dis.readInt();
			if(pos==-1)
			{
				break;
			}
			
			int k=0;
			int yPosition = pos/Main.width;
			int xPosition = pos%Main.width;
			
			while(xPosition+k<Main.data[0].length&&k<Main.interval)
			{
				Main.data[yPosition][xPosition+k] = dis.readDouble();
				k++;
			}

			System.out.println("READ DATA " + pos + " BACK");

			
		}
		
		System.out.println("READ DATA FINISHED");

		printData();
		
		return;
		
	}

	
	
	
	private void printData() {
		
		try {
			
		File root = Environment.getExternalStorageDirectory();
		File f = null;
		
		if(root.canWrite() ){
		    f = new File(root, "final.txt" );
		    FileWriter fw = new FileWriter(f);
		    BufferedWriter out = new BufferedWriter(fw);
		    
		    for(int i=0; i<Main.data.length; i++)
		    	for(int j=0; j<Main.data[0].length; j++)
		    	{
					if(j!=Main.data[0].length-1)
						out.write(new Double(Main.data[i][j]).toString()+" ");
					else
						out.write(new Double(Main.data[i][j]).toString()+"\n");				
		    	}
		
		    out.close();
		    
			}
		else
			System.out.println("FILE CANNOT WRITE");
		} catch (IOException e) {
			System.out.println("CANNOT CREATE FILE");
			e.printStackTrace();
			return;
		}

	}




	@Override
	public void run() {
			
		if(type=="ACTIVE")
		{
			//NEED TO GET THING BACK
			ServerSocket ss=null;
			try {
				ss = new ServerSocket(Main.AGRREGATIONPORT);
			} catch (IOException e) {
				System.out.println("Agggregation: IOEXCEPTION 1");
				e.printStackTrace();
				return;
			}
			
			Socket clientS;
			try {
				clientS = ss.accept();
			} catch (IOException e) {
				System.out.println("Agggregation: IOEXCEPTION 2");
				e.printStackTrace();
				return;
			}
			
			try {
				updateResult(clientS);
			} catch (IOException e) {
				System.out.println("EXCEPTION IN AGG, READING RESULT");
				e.printStackTrace();
			}	finally{
				try {
					clientS.close();
					ss.close();
				} catch (IOException e) {
					System.out.println("AGG: CLOSING SOCKET EXC: 104");
					e.printStackTrace();
				}
				
			}
			
			return;
			
		}
		
		else
		{
			
			Socket s=null;
			boolean flag = true;
			while(flag){
			try {
				s = new Socket(Main.ipAddress, Main.AGRREGATIONPORT);
				flag = false;
				sendResult(s);

			} catch (UnknownHostException e) {
				System.out.println("UNKNOWN HOST, WILL NOT TRY AGAIN");
				e.printStackTrace();
				return;
			} catch (IOException e) {
				System.out.println("IOE in AGG, SLEEP 1 second and try again");
				e.printStackTrace();
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e1) {
					System.out.println("SHOULD NOT HAPPEN, INTER EX, AGG");
					e1.printStackTrace();
					return;
				}
			}
			
			}
			
			try {
				s.close();
			} catch (IOException e) {
				System.out.println("AGG: IOE: 176");
				e.printStackTrace();
			}
			
			return;
		}
		
		
	
			
	}




	private void sendResult(Socket s) throws IOException {
		
		OutputStream out = s.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);

		while(!Main.final_result.isEmpty()){
			int pos = Main.final_result.remove(0);
			dos.writeInt(pos);
			int yPos = pos/Main.width;
			int xPos = pos%Main.width;
			
			int k=0;
			while(xPos+k<Main.data[0].length&&k<Main.interval){
				dos.writeDouble(Main.data[yPos][xPos+k]);
				k++;
			}
			
			
		}
		
		System.out.println("PASSED DATA FINISHED");

		dos.writeInt(-1);
		
	}
	

}
